//methods to test the functions in word32

#include "test_lfsr32.h"

//main method
//calls the other methods
//return true if all test pass
//false if one of the tests fail
bool test_lfsr32(){
  std::cout << "Testing lfsr32" << std::endl;
  
  //test the different constructors
  bool status = test_lfsr32_construct();
  if(status==false)
    return status;
  std::cout << "Passed: constructor\n";

 //test the different init for state and polynomial
  status = test_lfsr32_init();
  if(status==false)
    return status;
  std::cout << "Passed: lfsr32 init\n";

//test the different init for state and polynomial
  status = test_lfsr32_clock();
  if(status==false)
    return status;
  std::cout << "Passed: lfsr32 clock\n";
   
  //return true when all tests passed
  return true;
}

bool test_lfsr32_construct(){
  //default constructor
  lfsr32 lfsrA;
  int length=lfsrA.getLength();
  if(length!=32){
    std::cout << "Failed: standard constructor\n";
    return false;
  }
  //constructor setting length
  lfsr32 lfsrB(4);
  length=lfsrB.getLength();
  if(length!=4){
    std::cout << "Failed: constructor size\n";
    return false;
  }
  //return true if all test cases pass
  return true;
  
}


//test init state and polynomial
bool test_lfsr32_init(){
  
  lfsr32 lfsrA;
  //start to set state with word32
  word32 state(0x12341234);
  lfsrA.initState(state);
  int length=lfsrA.getLength();
  std::string refString="00101100010010000010110001001000";
  std::string testString=lfsrA.getState().toBinStringLSB();
  if((length!=32)||(testString!=refString)){
    std::cout << "Failed: initState(word32)\n";
    return false;
  }
  //set state with unsigned long 
  lfsrA.initState(0x9aaa5551uL);
  refString="10001010101010100101010101011001";
  testString=lfsrA.getState().toBinStringLSB();
  length=lfsrA.getLength();
  if((length!=32)||(testString!=refString)){
    std::cout << "Failed: initState(unsigned long)\n";
    return false;
  }
  //set state with string
  lfsrA.initState("1011");
  refString="10110000000000000000000000000000";
  testString=lfsrA.getState().toBinStringLSB();
  length=lfsrA.getLength();
  if((length!=4)||(testString!=refString)){
    std::cout << "Failed: initState(string)\n";
    return false;
  }

  //if all test pass for init state then all test must also pass for initPoly
  //since they are using the same kind of implementation

  //return true if all test cases pass

  return true;
}

//test clock
bool test_lfsr32_clock(){

  //test a lfsr with length 4
  //sn=sn-1+sn-4
  //given initial state 1000 (LSB)
  //a 32-bit output should be
  //10001111010110010001111010110010 (LSB)
  lfsr32 lfsr(4); 
  lfsr.initState(1);
  lfsr.initPoly("1001");
  word32 outWord;
  for(int i=0;i<32;i++){
    int b=lfsr.clock();
    outWord.setVal(i,b);
  }
  std::string refString="10001111010110010001111010110010";
  std::string testString=outWord.toBinStringLSB();
  if(testString!=refString){
    std::cout << "Failed: step\n";
    return false;
  }
  //run a test with clock32
  //take a longer polynomial length 11
  //sn=sn-2 + sn-5+ sn-9+ sn-11
  lfsr.resize(11);
  lfsr.initPoly("10100010010");
  lfsr.initState("00010110011");
  refString="1662727A";
  outWord=lfsr.clock32();
  testString=outWord.toHexStringLSB();
  if(testString!=refString){
    std::cout << "Failed: step32\n";
    return false;
  }
  //return true if all test pass
  return true;
}
